import 'dart:async';
import 'dart:io';
import 'dart:math';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_im_demo/db/db_help.dart';
import 'package:flutter_im_demo/http/dio.dart';
import 'package:flutter_im_demo/model/file_model.dart';
import 'package:flutter_im_demo/model/friend_model.dart';
import 'package:flutter_im_demo/model/message_model.dart';
import 'package:flutter_im_demo/state/global_state.dart';
import 'package:flutter_im_demo/widget/loading_widget.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid/uuid.dart';
import 'package:provider/provider.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';

import '../const_value.dart';
import '../utils.dart';
import 'friend_list_page.dart';

class ChatPage extends StatefulWidget {
  final Friend friend;
  final String myId;

  const ChatPage({Key key, this.friend, this.myId}) : super(key: key);

  @override
  _ChatPageState createState() => _ChatPageState();
}

class _ChatPageState extends State<ChatPage> {
  var _textController;

  // 滚动控制器
  ScrollController _scrollController;
  EasyRefreshController _easyRefreshController;

  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController();
    _textController = TextEditingController();
    _easyRefreshController = EasyRefreshController();
  }

  @override
  Widget build(BuildContext context) {
    final String title =
        (widget.friend.note == null || widget.friend.note.isEmpty)
            ? widget.friend.nickName
            : widget.friend.note;
    return Scaffold(
      appBar: AppBar(
        leading: Consumer<GlobalState>(builder: (context, state, _) {
          return IconButton(
              icon: Icon(Icons.arrow_back_ios),
              onPressed: () {
                state.setFriend(null);
                Navigator.of(context).pop();
              });
        }),
        title: Row(
          children: <Widget>[
            MyCircleAvatar(
              height: 40.0,
              avatar: widget.friend.avatar,
              tag: widget.friend.id,
            ),
            const SizedBox(width: 10.0),
            Expanded(
                child: Text(
              title,
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
            )),
          ],
        ),
        flexibleSpace: Container(
          decoration: BoxDecoration(gradient: gradientColor),
        ),
        actions: <Widget>[
          IconButton(
            onPressed: () {},
            icon: Icon(Icons.more_horiz),
          ),
        ],
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            Expanded(
              child: GestureDetector(
                behavior: HitTestBehavior.translucent,
                onTap: () {
                  FocusScope.of(context).requestFocus(FocusNode());
                },
                child: Container(
                  color: chatListBackgroundColor,
                  child: Consumer<GlobalState>(
                    builder: (context, state, _) {
                      return WillPopScope(
                        onWillPop: () async {
                          state.setFriend(null);
                          return true;
                        },
                        child: EasyRefresh.custom(
                          scrollController: _scrollController,
                          reverse: true,
                          footer: CustomFooter(
                              enableInfiniteLoad: state.moreFlag,
                              extent: 40.0,
                              triggerDistance: 50.0,
                              footerBuilder: (context,
                                  loadState,
                                  pulledExtent,
                                  loadTriggerPullDistance,
                                  loadIndicatorExtent,
                                  axisDirection,
                                  float,
                                  completeDuration,
                                  enableInfiniteLoad,
                                  success,
                                  noMore) {
                                return Stack(
                                  children: <Widget>[
                                    Positioned(
                                      bottom: 0.0,
                                      left: 0.0,
                                      right: 0.0,
                                      child: Container(
                                        width: 30.0,
                                        height: 30.0,
                                        child: SpinKitFadingCube(
                                          color: color3,
                                          size: loadingWidgetSize,
                                        ),
                                      ),
                                    ),
                                  ],
                                );
                              }),
                          slivers: <Widget>[
                            SliverList(
                              delegate: SliverChildBuilderDelegate(
                                (context, index) {
                                  final msg = state.getMessage(index);
                                  return MessageItemWidget(
                                    key: Key(msg.mid),
                                    message: msg,
                                    friendId: widget.friend.id,
                                    onTap: () {
                                      Navigator.of(context).pushNamed("watchImage",
                                          arguments: state.getImageUrlList());
                                    },
                                  );
                                },
                                childCount: state.messageListLen(),
                              ),
                            ),
                          ],
                          onLoad: () async {
                            if (state.moreFlag) {
                              await Future.delayed(Duration(seconds: 2),
                                  () async {
                                bool moreFlag =
                                    await state.queryHistoryMessage();
                                print("还有更多数据? ${moreFlag ? "有" : "没有了"}");
                              });
                            }
                          },
                        ),
                      );
                    },
                  ),
                ),
              ),
            ),
            _inputWidget(),
          ],
        ),
      ),
    );
  }

  Widget _inputWidget() {
    return Container(
      height: 70.0,
      padding: const EdgeInsets.all(14.0),
      color: chatInputColor,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Container(
              width: 40.0,
              height: 40.0,
              alignment: Alignment.center,
              decoration: BoxDecoration(
                  boxShadow: [
                    BoxShadow(
                        color: Colors.black38,
                        offset: Offset(2.0, 2.0),
                        blurRadius: 5.0,
                        spreadRadius: 1.0),
                  ],
                  borderRadius: BorderRadius.circular(20.0),
                  color: Colors.white),
              child: Consumer<GlobalState>(builder: (context, state, _) {
                return IconButton(
                  icon: Icon(Icons.add),
                  color: Colors.black,
                  onPressed: () async {
                    await _addOnPressed(context, state);
                  },
                );
              })),
          Expanded(
            child: TextField(
              decoration: InputDecoration(
                border: InputBorder.none,
                contentPadding: EdgeInsets.all(10.0),
              ),
              controller: _textController,
            ),
          ),
          Container(
            width: 40.0,
            height: 40.0,
            alignment: Alignment.center,
            decoration: BoxDecoration(
                boxShadow: [
                  BoxShadow(
                      color: Colors.black38,
                      offset: Offset(2.0, 2.0),
                      blurRadius: 5.0,
                      spreadRadius: 1.0),
                ],
                borderRadius: BorderRadius.circular(20.0),
                gradient: gradientColor),
            child: Consumer<GlobalState>(builder: (context, state, _) {
              return IconButton(
                onPressed: () async {
                  final msg = _textController.text;
                  _textController.clear();
                  if (msg.isNotEmpty) {
                    final msgModel = _createMsg(state.userInfoModel.id, msg);
                    await state.addMessage(msgModel);
                    state.sendMsg(msgModel);
                  }
                },
                icon: Icon(
                  FontAwesomeIcons.solidPaperPlane,
                  size: 18.0,
                  color: Colors.white,
                ),
              );
            }),
          ),
        ],
      ),
    );
  }

  Message _createMsg(String fromId, String body) {
    return Message(
        mid: Uuid().v4().replaceAll("-", ""),
        body: body,
        fromId: fromId,
        toId: widget.friend.id,
        status: 0,
        readFlag: 0,
        combKey: fromId + widget.friend.id);
  }

  @override
  void dispose() {
    _textController.dispose();
    _scrollController.dispose();
    _easyRefreshController.dispose();
    super.dispose();
  }

  Future<String> _uploadFile(File file, String fileName) async {
    FormData formData =
        FormData.from({"file": new UploadFileInfo(file, fileName)});
    final response = await dio.post("/fileUpload", data: formData);
    print(response);
    final respMap = response.data as Map;
    int code = respMap["code"];
    if (code == 1) {
      String url =
          "http://$HTTP_SERVER_HOST:$HTTP_SERVER_PORT${respMap['data']['url']}";
      print("url: $url");
      return url;
    } else {
      print("ERROR: ${respMap}");
      return null;
    }
  }

  Future<void> _addOnPressed(BuildContext context, GlobalState state) async {
    print("_addOnPressed");
    await showModalBottomSheet(
        context: context,
        builder: (BuildContext context) {
          File imageFile;
          return Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              ListTile(
                leading: Icon(Icons.photo_camera),
                title: Text("Camera"),
                onTap: () async {
                  imageFile =
                      await ImagePicker.pickImage(source: ImageSource.camera);
                  _imageUpload(imageFile, state);
                  Navigator.pop(context);
                },
              ),
              ListTile(
                leading: Icon(Icons.photo_library),
                title: Text("Gallery"),
                onTap: () async {
                  imageFile =
                      await ImagePicker.pickImage(source: ImageSource.gallery);
                  _imageUpload(imageFile, state);
                  Navigator.pop(context);
                },
              ),
            ],
          );
        });
  }

  Future<FileModel> _createFileModel(
      String mid, File file, bool isImage) async {
    int width = null;
    int height = null;
    int size = 0;
    String fileName = getBaseName(file.path);
    if (isImage) {
      var decodedImage = await decodeImageFromList(file.readAsBytesSync());
      width = decodedImage.width;
      height = decodedImage.height;
    } else {
      size = await file.length();
    }
    final model = FileModel(
        mid: mid,
        isImage: isImage,
        fileName: fileName,
        width: width,
        height: height,
        size: size);
    final database = await dbHelp.database;
    await database.rawInsert(FileModel.insertSQL, model.getInsertArgs());
    return model;
  }

  Future<Message> fileModelToMessage(FileModel fileModel, String mid) async {
    final msg = Message(
        mid: mid,
        fromId: widget.myId,
        toId: widget.friend.id,
        body: fileModel.id,
        type: fileModel.isImage ? 2 : 3,
        combKey: widget.myId + widget.friend.id);
    msg.fileModel = fileModel;
    final database = await dbHelp.database;
    await database.rawInsert(Message.insertSQL, msg.getInsertArguments());
    return msg;
  }

  Future<void> _imageUpload(File imageFile, GlobalState state) async {
    print("imageFile: ${imageFile.path}");
    String mid = Uuid().v4().replaceAll("-", "");
    final FileModel fileModel = await _createFileModel(mid, imageFile, true);
    final Message m = await fileModelToMessage(fileModel, mid);
    print("fileModelToMessage: $m");
    state.addFileMessage(m);
    _uploadFile(imageFile, fileModel.fileName).then((url) {
      if (url != null) {
        state.updateMessageToImage(url, m);
      }
    });
  }
}

const _imageLoadingWidget = SizedBox(
    child: Center(
        child: CircularProgressIndicator(
            valueColor: AlwaysStoppedAnimation<Color>(
      Colors.grey,
    ))),
    width: 30.0,
    height: 30.0);

class MessageItemWidget extends StatelessWidget {
  final Message message;
  final String friendId;
  final VoidCallback onTap;

  const MessageItemWidget({Key key, this.message, this.friendId, this.onTap})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    final friendMsgFlag = message.fromId == friendId;
    Widget child = _getMessageWidgetChild(message, size, context);
//    Widget bodyWidget = _getMessageBody(context, message, friendMsgFlag);
    return Row(
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment:
          friendMsgFlag ? MainAxisAlignment.start : MainAxisAlignment.end,
      children: <Widget>[
        !friendMsgFlag
            ? SizedBox(
                width: 36.0,
              )
            : Container(),
        Flexible(
          child: Container(
            margin: EdgeInsets.only(top: 10.0, bottom: 10.0),
            padding: EdgeInsets.all(12.0),
            decoration: BoxDecoration(
              boxShadow: [
                BoxShadow(
                    color: Colors.black26,
                    offset: Offset(0.0, 2.0),
                    blurRadius: 10.0,
                    spreadRadius: 1.0),
              ],
              gradient: friendMsgFlag
                  ? LinearGradient(
                      colors: [Colors.white, Colors.white],
                    )
                  : gradientColor,
              borderRadius: friendMsgFlag
                  ? BorderRadius.horizontal(right: Radius.circular(14.0))
                  : BorderRadius.horizontal(left: Radius.circular(14.0)),
            ),
            child: child,
//          child: Text(message.body,
//              textAlign: TextAlign.start, style: TextStyle(fontSize: 16.0)),
          ),
        ),
//      bodyWidget,
        friendMsgFlag
            ? SizedBox(
                width: 36.0,
              )
            : Container(),
      ],
    );
  }

  Widget _getMessageWidgetChild(Message msg, Size size, BuildContext context) {
    Widget body = Container();
    switch (msg.type) {
      case 0:
        body = Text(message.body,
            textAlign: TextAlign.start, style: TextStyle(fontSize: 16.0));
        break;

      case 1:
//        body = "[语音]";
        break;

      case 2:
        String url = msg.fileModel != null ? msg.fileModel.url : msg.body;
        final imageModel = getImageModel(size.width, size.height, msg);
        body = url.isNotEmpty
            ? GestureDetector(
                onTap: onTap,
                child: Container(
                  child: CachedNetworkImage(
                    imageUrl: url,
                    placeholder: (context, url) => _imageLoadingWidget,
                    errorWidget: (context, url, error) => Icon(
                          Icons.error,
                          color: Colors.white,
                        ),
                  ),
                  width: imageModel.width,
                  height: imageModel.height,
                ),
              )
            : Container(
                width: imageModel.width,
                height: imageModel.height,
                color: Colors.grey,
              );
        break;

      case 3:
//        body = "[文件]";
    }

    return body;
  }

  Widget _getMessageBody(
      BuildContext context, Message message, bool friendMsgFlag) {
    final size = MediaQuery.of(context).size;
    switch (message.type) {
      case 0:
        return Flexible(
          child: Container(
            margin: EdgeInsets.only(top: 10.0, bottom: 10.0),
            padding: EdgeInsets.all(12.0),
            decoration: BoxDecoration(
              boxShadow: [
                BoxShadow(
                    color: Colors.black26,
                    offset: Offset(0.0, 2.0),
                    blurRadius: 10.0,
                    spreadRadius: 1.0),
              ],
              gradient: friendMsgFlag
                  ? LinearGradient(
                      colors: [Colors.white, Colors.white],
                    )
                  : gradientColor,
              borderRadius: friendMsgFlag
                  ? BorderRadius.horizontal(right: Radius.circular(14.0))
                  : BorderRadius.horizontal(left: Radius.circular(14.0)),
            ),
            child: Text(message.body,
                textAlign: TextAlign.start, style: TextStyle(fontSize: 16.0)),
          ),
        );

      case 1:
//        body = "[语音]";
        return null;

      case 2:
        print(
            "chat item width: ${message.fileModel.width}, height: ${message.fileModel.height}");
//        double width = message.fileModel.width < (size.width * 0.7) ? message.fileModel.width : ;
//        double height = 0.0;

        return message.fileModel.url.isNotEmpty
            ? Container(
                margin: EdgeInsets.only(top: 10.0, bottom: 10.0),
                padding: EdgeInsets.all(12.0),
                child: CachedNetworkImage(
                  fit: BoxFit.cover,
                  width: message.fileModel.width * 0.3,
                  height: message.fileModel.height * 0.3,
                  imageUrl: message.fileModel.url,
                  placeholder: (context, url) =>
                      new CircularProgressIndicator(),
                  errorWidget: (context, url, error) => new Icon(Icons.error),
                ),
                width: message.fileModel.width * 0.3,
                height: message.fileModel.height * 0.3,
              )
            : Container(
                margin: EdgeInsets.only(top: 10.0, bottom: 10.0),
                padding: EdgeInsets.all(12.0),
                width: message.fileModel.width * 0.5,
                height: message.fileModel.height * 0.5,
                color: Colors.grey,
              );

      case 3:
//        body = "[文件]";
        return null;
    }
  }
}

ImageModel getImageModel(double screenWidth, double screenHeight, Message msg) {
  screenWidth = screenWidth / 2;
  screenHeight = screenHeight / 2;
  double newWidth = 0.0;
  double newHeight = 0.0;
  if (msg.fileModel == null) {
    newWidth = msg.width.toDouble();
    newHeight = msg.height.toDouble();
  } else {
    newWidth = msg.fileModel.width.toDouble();
    newHeight = msg.fileModel.height.toDouble();
  }
  while (newWidth > screenWidth || newHeight > screenHeight) {
    newWidth = newWidth / 2;
    newHeight = newHeight / 2;
  }
  return ImageModel(newWidth, newHeight);
}

class ImageModel {
  final double width;
  final double height;

  ImageModel(this.width, this.height);

  @override
  String toString() {
    return 'ImageModel{width: $width, height: $height}';
  }
}

///EasyRefresh(
////                              key: _easyRefreshKey,
////                              behavior: ScrollOverBehavior(),
////                              refreshHeader: _refreshHeader(),
////                              refreshFooter: _refreshFooter(),
////                              child: ListView.builder(
////                                reverse: true,
////                                itemBuilder: (context, index) {
////                                  final msg = state.getMessage(index);
////                                  return MessageItemWidget(
////                                    key: Key(msg.mid),
////                                    message: msg,
////                                    friendId: widget.friend.id,
////                                  );
////                                },
////                                itemCount: state.messageListLen(),
////                              ),
////                            ),
